package com.bix.util.blizfiles.mpq;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;

public class MPQBlockTable {
	public	static	int	BLOCK_TABLE_SIZE = 4 + 4 + 4 + 4;
	
	//
	// Offset of the beginning of the block, relative to the beginning of the
	// archive.
	//
	private	int	blockOffset;
	
	//
	// Size of the block in the archive.
	//
	private	int	blockSize;
	
	//
	// Size of the file data stored in the block. Only valid if the block is a
	// file; otherwise meaningless, and should be 0. If the file is compressed,
	// this is the size of the uncompressed file data.
	//
	private	int	fileSize;
	
	//
	// Bit mask of the flags for the block. The following values are conclusively
	// identified:
	// 	80000000h:	Block is a file, and follows the file data format; otherwise,
	// 							block is free space or unused. If the block is not a file,
	//							all other flags should be cleared, and FileSize should be 0.
	//	01000000h:	File is stored as a single unit, rather than split into
	//							sectors.
	//	00020000h:	The file's encryption key is adjusted by the block offset and
	// 							file size (explained in detail in the File Data section).
	//							File must be encrypted.
	//	00010000h:	File is encrypted.
	//	00000200h:	File is compressed. File cannot be imploded.
	//	00000100h:	File is imploded. File cannot be compressed.
	//
	private	int	flags;
	
	/**
	 * Read the block table from a byte buffer.  This will work or throw an
	 * underflow exception if not data is available.
	 * 
	 * @param bb
	 */
	public void read (ByteBuffer bb) {
		this.blockOffset = bb.getInt ();
		this.blockSize = bb.getInt ();
		this.fileSize = bb.getInt ();
		this.flags = bb.getInt ();
	}
	
	public boolean read (FileChannel fc) throws IOException {
		ByteBuffer	bb = ByteBuffer.allocate (BLOCK_TABLE_SIZE);
		if (fc.read(bb)< BLOCK_TABLE_SIZE) {
			return false;
		}
		bb.rewind ();
		bb.order (ByteOrder.LITTLE_ENDIAN);
		this.read(bb);
		return true;
	}
}